package genedit.view.graph;

import genedit.gui.GMainFrame;
import genedit.model.Document;
import genedit.model.Workspace;
import genedit.model.graph.BreakPoint;
import genedit.model.graph.GraphElement;
import genedit.model.graph.Link;
import genedit.model.graph.SubdocumentElement;

import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.util.Iterator;

public class SubdocumentElementPainter extends MyRectPainter {
	
	public SubdocumentElementPainter(GraphElement element) {
		super(element);
	}

	@Override
	public void paint(Graphics2D g) {
		super.paint(g);
		
		SubdocumentElement subdocument=(SubdocumentElement)getElement();
		GraphDocumentView subdocumentView=GMainFrame.getInstance().getGraphDocumentView(subdocument.getSubDocument());
		if(subdocumentView==null){
			subdocumentView=new GraphDocumentView(subdocument.getSubDocument());
		}
		GraphWorkArea subdocumentGraphWorkArea=(GraphWorkArea)subdocumentView.getWorkArea();
		
		double backupScale=subdocumentGraphWorkArea.scaling;
		double backupTranslateX=subdocumentGraphWorkArea.translateX;
		double backupTranslateY=subdocumentGraphWorkArea.translateY;
		bestFit(subdocumentView, getShape());
		AffineTransform backupTransform=g.getTransform();
		g.transform(getTransform());
		g.transform(((GraphWorkArea)subdocumentView.getWorkArea()).getTransformation());
		
		for(ElementPainter painter :subdocumentView.getElementPainters()){
			painter.paint(g);
		}
		g.setTransform(backupTransform);
		subdocumentGraphWorkArea.setScaling(backupScale);
		subdocumentGraphWorkArea.setTranslateX(backupTranslateX);
		subdocumentGraphWorkArea.setTranslateY(backupTranslateY);
		subdocumentGraphWorkArea.setupTransformation();
		
		g.setClip(null);
	}
	
	protected static void bestFit(GraphDocumentView documentView,Shape border){
		if (documentView == null || documentView.getElementPainters().size() == 0)
			return;

		Dimension windowSize =border.getBounds().getSize();

		Iterator<GraphElement> it = null;
		it = documentView.getModel().getIteratorElements();
		double minX = Double.MAX_VALUE, maxX = Double.MIN_VALUE;
		double minY = Double.MAX_VALUE, maxY = Double.MIN_VALUE;

		while (it.hasNext()) {
			GraphElement currentElement = it.next();
			if (!(currentElement instanceof Link)) {
				Point2D positionOfElement = currentElement.getPosition();
				Dimension sizeOfElement = currentElement.getSize();

				minX = Math.min(minX, positionOfElement.getX());
				maxX = Math.max(maxX, positionOfElement.getX() + sizeOfElement.getWidth());
				minY = Math.min(minY, positionOfElement.getY());
				maxY = Math.max(maxY, positionOfElement.getY() + sizeOfElement.getHeight());
			} else {
				Link linkElement = (Link) currentElement;
				Iterator<BreakPoint> itPoints = linkElement.getIteratorBreakPoints();
				while (itPoints.hasNext()) {
					BreakPoint bp = itPoints.next();
					minX = Math.min(minX, bp.getPosition().getX() - 30);
					maxX = Math.max(maxX, bp.getPosition().getX() - 15);
					minY = Math.min(minY, bp.getPosition().getY() - 30);
					maxY = Math.max(maxY, bp.getPosition().getY() - 15);
				}
			}
		}

		double neededWidth = maxX - minX;
		double neededHeight = maxY - minY;

		double scaleFactor1 = windowSize.getHeight() / neededHeight;
		double scaleFactor2 = windowSize.getWidth() / neededWidth;
		
		double scaleFactor = Math.min(scaleFactor1,scaleFactor2);

		GraphWorkArea workArea = ((GraphWorkArea) documentView.getWorkArea());
		workArea.scaling=scaleFactor * 0.95;
		workArea.setTranslateX(-minX);
		workArea.setTranslateY(-minY);
		workArea.setupTransformation();
	}
}
